#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file motor_service.py
@brief 电机业务服务类
@details 提供电机控制业务逻辑，连接驱动层和界面层
@author Motor Controller Team
@date 2024
"""

import logging
import time
from typing import Optional, Dict, Any, Callable
from enum import Enum

from drivers import ModbusDriver, MotorDriver
from drivers.uart_driver import UARTDriver
from core.config import ConfigManager, SerialConfig, MotorConfig, UARTConfig
from core.logging_config import get_logger

logger = get_logger(__name__)


class ConnectionState(Enum):
    """连接状态枚举"""
    DISCONNECTED = "disconnected"
    CONNECTING = "connecting"
    CONNECTED = "connected"
    ERROR = "error"


class MotorService:
    """
    @brief 电机业务服务类
    @details 提供电机控制业务逻辑
    """
    
    def __init__(self, config_manager: ConfigManager):
        """
        @brief 初始化电机服务
        @param config_manager 配置管理器
        """
        self.config_manager = config_manager
        self.modbus_driver: Optional[ModbusDriver] = None
        self.motor_driver: Optional[MotorDriver] = None
        self.uart_driver: Optional[UARTDriver] = None
        self.connection_state = ConnectionState.DISCONNECTED
        
        # 回调函数
        self.connection_callback: Optional[Callable] = None
        self.status_callback: Optional[Callable] = None
        self.error_callback: Optional[Callable] = None
        
        logger.info("电机服务初始化完成")
    
    def set_connection_callback(self, callback: Callable) -> None:
        """
        @brief 设置连接状态回调
        @param callback 回调函数
        """
        self.connection_callback = callback
    
    def set_status_callback(self, callback: Callable) -> None:
        """
        @brief 设置状态回调
        @param callback 回调函数
        """
        self.status_callback = callback
    
    def set_error_callback(self, callback: Callable) -> None:
        """
        @brief 设置错误回调
        @param callback 回调函数
        """
        self.error_callback = callback
    
    def connect(self) -> bool:
        """
        @brief 连接到电机驱动器
        @return bool 连接是否成功
        """
        if self.connection_state == ConnectionState.CONNECTED:
            logger.warning("已经连接到电机驱动器")
            return True
        
        self.connection_state = ConnectionState.CONNECTING
        self._notify_connection_state()
        
        try:
            # 获取串口配置
            serial_config = self.config_manager.get_serial_config()
            
            # 创建Modbus驱动
            self.modbus_driver = ModbusDriver(
                port=serial_config.port,
                baudrate=serial_config.baudrate,
                device_id=serial_config.device_id,
                timeout=serial_config.timeout,
                bytesize=serial_config.bytesize,
                parity=serial_config.parity,
                stopbits=serial_config.stopbits
            )
            
            # 连接到设备
            if self.modbus_driver.connect():
                # 创建电机驱动
                self.motor_driver = MotorDriver(self.modbus_driver)
                
                self.connection_state = ConnectionState.CONNECTED
                logger.info("电机服务连接成功")
                self._notify_connection_state()
                return True
            else:
                self.connection_state = ConnectionState.ERROR
                logger.error("电机服务连接失败")
                self._notify_connection_state()
                return False
                
        except Exception as e:
            self.connection_state = ConnectionState.ERROR
            logger.error(f"电机服务连接异常: {e}")
            self._notify_connection_state()
            if self.error_callback:
                self.error_callback(f"连接异常: {e}")
            return False
    
    def disconnect(self) -> None:
        """
        @brief 断开连接
        """
        if self.connection_state == ConnectionState.DISCONNECTED:
            return
        
        try:
            # 停止电机
            if self.motor_driver:
                self.motor_driver.stop_motors()
            
            # 断开Modbus连接
            if self.modbus_driver:
                self.modbus_driver.disconnect()
            
            self.modbus_driver = None
            self.motor_driver = None
            self.connection_state = ConnectionState.DISCONNECTED
            
            logger.info("电机服务已断开连接")
            self._notify_connection_state()
            
        except Exception as e:
            logger.error(f"断开连接异常: {e}")
            if self.error_callback:
                self.error_callback(f"断开连接异常: {e}")
    
    def is_connected(self) -> bool:
        """
        @brief 检查是否已连接
        @return bool 是否已连接
        """
        return (self.connection_state == ConnectionState.CONNECTED and 
                self.modbus_driver is not None and 
                self.motor_driver is not None)
    
    def test_connection(self) -> bool:
        """
        @brief 测试连接
        @return bool 连接是否正常
        """
        if not self.is_connected():
            return False
        
        try:
            return self.modbus_driver.test_communication()
        except Exception as e:
            logger.error(f"测试连接异常: {e}")
            if self.error_callback:
                self.error_callback(f"测试连接异常: {e}")
            return False
    
    def test_serial_config(self) -> bool:
        """
        @brief 测试串口配置（不建立真实连接）
        @return bool 串口配置是否可用
        """
        try:
            # 获取串口配置
            serial_config = self.config_manager.get_serial_config()
            
            # 创建临时Modbus驱动进行测试
            from drivers.modbus_driver import ModbusDriver
            temp_driver = ModbusDriver(
                port=serial_config.port,
                baudrate=serial_config.baudrate,
                device_id=serial_config.device_id,
                timeout=serial_config.timeout,
                bytesize=serial_config.bytesize,
                parity=serial_config.parity,
                stopbits=serial_config.stopbits
            )
            
            # 尝试连接
            success = temp_driver.connect()
            if success:
                # 连接成功，立即断开
                temp_driver.disconnect()
                logger.info(f"串口配置测试成功: {serial_config.port}")
                return True
            else:
                logger.warning(f"串口配置测试失败: {serial_config.port}")
                return False
                
        except Exception as e:
            logger.error(f"串口配置测试异常: {e}")
            if self.error_callback:
                self.error_callback(f"串口配置测试异常: {e}")
            return False
    
    def send_serial_command(self, command: str) -> str:
        """
        @brief 发送串口命令
        @param command 要发送的命令
        @return str 发送结果
        """
        try:
            if not self.modbus_driver or not self.modbus_driver.is_connected():
                return "错误: 串口未连接"
            
            # 发送命令到串口
            result = self.modbus_driver.send_command(command)
            logger.info(f"串口命令发送: {command} -> {result}")
            return result
            
        except Exception as e:
            logger.error(f"发送串口命令异常: {e}")
            if self.error_callback:
                self.error_callback(f"发送串口命令异常: {e}")
            return f"错误: {e}"
    
    def receive_serial_data(self) -> str:
        """
        @brief 接收串口数据
        @return str 接收到的数据
        """
        try:
            if not self.modbus_driver or not self.modbus_driver.is_connected():
                return "错误: 串口未连接"
            
            # 从串口接收数据
            data = self.modbus_driver.receive_data()
            if data:
                logger.info(f"串口数据接收: {data}")
                return data
            else:
                return "无数据"
                
        except Exception as e:
            logger.error(f"接收串口数据异常: {e}")
            if self.error_callback:
                self.error_callback(f"接收串口数据异常: {e}")
            return f"错误: {e}"
    
    def start_serial_terminal(self) -> bool:
        """
        @brief 启动串口终端
        @return bool 启动是否成功
        """
        try:
            if not self.modbus_driver or not self.modbus_driver.is_connected():
                logger.warning("串口终端启动失败: 串口未连接")
                return False
            
            # 启动串口终端模式
            logger.info("串口终端已启动")
            return True
            
        except Exception as e:
            logger.error(f"启动串口终端异常: {e}")
            if self.error_callback:
                self.error_callback(f"启动串口终端异常: {e}")
            return False
    
    def stop_serial_terminal(self) -> bool:
        """
        @brief 停止串口终端
        @return bool 停止是否成功
        """
        try:
            # 停止串口终端模式
            logger.info("串口终端已停止")
            return True
            
        except Exception as e:
            logger.error(f"停止串口终端异常: {e}")
            if self.error_callback:
                self.error_callback(f"停止串口终端异常: {e}")
            return False
    
    def start_motors(self, left_speed: int = 500, right_speed: int = 500) -> bool:
        """
        @brief 启动电机
        @param left_speed 左电机转速
        @param right_speed 右电机转速
        @return bool 启动是否成功
        """
        if not self.is_connected():
            error_msg = "未连接到电机驱动器"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            # 验证转速范围
            motor_config = self.config_manager.get_motor_config()
            if not self._validate_speed(left_speed, motor_config):
                error_msg = f"左电机转速超出范围: {left_speed}"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
                return False
            
            if not self._validate_speed(right_speed, motor_config):
                error_msg = f"右电机转速超出范围: {right_speed}"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
                return False
            
            success = self.motor_driver.start_motors(left_speed, right_speed)
            if success:
                logger.info(f"电机启动成功 - 左电机: {left_speed}, 右电机: {right_speed}")
            else:
                error_msg = "电机启动失败"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
            
            return success
            
        except Exception as e:
            error_msg = f"启动电机异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def stop_motors(self) -> bool:
        """
        @brief 停止电机
        @return bool 停止是否成功
        """
        if not self.is_connected():
            error_msg = "未连接到电机驱动器"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            success = self.motor_driver.stop_motors()
            if success:
                logger.info("电机停止成功")
            else:
                error_msg = "电机停止失败"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
            
            return success
            
        except Exception as e:
            error_msg = f"停止电机异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def emergency_stop(self) -> bool:
        """
        @brief 急停电机
        @return bool 急停是否成功
        """
        if not self.is_connected():
            error_msg = "未连接到电机驱动器"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            success = self.motor_driver.emergency_stop()
            if success:
                logger.warning("电机急停成功")
            else:
                error_msg = "电机急停失败"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
            
            return success
            
        except Exception as e:
            error_msg = f"急停电机异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def set_motor_speed(self, left_speed: Optional[int] = None, 
                       right_speed: Optional[int] = None) -> bool:
        """
        @brief 设置电机转速
        @param left_speed 左电机转速
        @param right_speed 右电机转速
        @return bool 设置是否成功
        """
        if not self.is_connected():
            error_msg = "未连接到电机驱动器"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            # 验证转速范围
            motor_config = self.config_manager.get_motor_config()
            if left_speed is not None and not self._validate_speed(left_speed, motor_config):
                error_msg = f"左电机转速超出范围: {left_speed}"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
                return False
            
            if right_speed is not None and not self._validate_speed(right_speed, motor_config):
                error_msg = f"右电机转速超出范围: {right_speed}"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
                return False
            
            success = self.motor_driver.set_motor_speed(left_speed, right_speed)
            if success:
                logger.info(f"电机转速设置成功 - 左电机: {left_speed}, 右电机: {right_speed}")
            else:
                error_msg = "电机转速设置失败"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
            
            return success
            
        except Exception as e:
            error_msg = f"设置电机转速异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def phase_learning(self) -> bool:
        """
        @brief 执行相序学习
        @return bool 相序学习是否成功
        """
        if not self.is_connected():
            error_msg = "未连接到电机驱动器"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            success = self.motor_driver.phase_learning()
            if success:
                logger.info("相序学习成功")
            else:
                error_msg = "相序学习失败"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
            
            return success
            
        except Exception as e:
            error_msg = f"相序学习异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def reset_system(self) -> bool:
        """
        @brief 复位系统
        @return bool 复位是否成功
        """
        if not self.is_connected():
            error_msg = "未连接到电机驱动器"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            success = self.motor_driver.reset_system()
            if success:
                logger.info("系统复位成功")
            else:
                error_msg = "系统复位失败"
                logger.error(error_msg)
                if self.error_callback:
                    self.error_callback(error_msg)
            
            return success
            
        except Exception as e:
            error_msg = f"系统复位异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def get_motor_status(self) -> Optional[Dict[str, Any]]:
        """
        @brief 获取电机状态
        @return Optional[Dict[str, Any]] 电机状态信息
        """
        if not self.is_connected():
            return None
        
        try:
            return self.motor_driver.get_motor_status()
        except Exception as e:
            logger.error(f"获取电机状态异常: {e}")
            if self.error_callback:
                self.error_callback(f"获取电机状态异常: {e}")
            return None
    
    def _validate_speed(self, speed: int, motor_config: MotorConfig) -> bool:
        """
        @brief 验证转速是否在有效范围内
        @param speed 转速值
        @param motor_config 电机配置
        @return bool 转速是否有效
        """
        return (motor_config.left_motor_min_speed <= abs(speed) <= motor_config.left_motor_max_speed or
                motor_config.right_motor_min_speed <= abs(speed) <= motor_config.right_motor_max_speed)
    
    def _notify_connection_state(self) -> None:
        """
        @brief 通知连接状态变化
        """
        if self.connection_callback:
            try:
                self.connection_callback(self.connection_state)
            except Exception as e:
                logger.error(f"连接状态回调异常: {e}")
    
    # ==================== UART串口日志监控相关方法 ====================
    
    def connect_uart(self) -> bool:
        """
        @brief 连接UART串口用于日志监控
        @return bool 连接是否成功
        """
        try:
            if self.uart_driver and self.uart_driver.is_connected():
                logger.info("UART串口已连接")
                return True
            
            # 获取UART配置
            uart_config = self.config_manager.get_uart_config()
            
            # 创建UART驱动
            self.uart_driver = UARTDriver(
                port=uart_config.port,
                baudrate=uart_config.baudrate,
                timeout=uart_config.timeout,
                bytesize=uart_config.bytesize,
                parity=uart_config.parity,
                stopbits=uart_config.stopbits
            )
            
            # 连接UART
            if self.uart_driver.connect():
                logger.info("UART串口连接成功")
                return True
            else:
                logger.error("UART串口连接失败")
                return False
                
        except Exception as e:
            logger.error(f"UART串口连接异常: {e}")
            if self.error_callback:
                self.error_callback(f"UART串口连接异常: {e}")
            return False
    
    def disconnect_uart(self) -> bool:
        """
        @brief 断开UART串口连接
        @return bool 断开是否成功
        """
        try:
            if self.uart_driver:
                result = self.uart_driver.disconnect()
                self.uart_driver = None
                logger.info("UART串口已断开")
                return result
            return True
        except Exception as e:
            logger.error(f"UART串口断开异常: {e}")
            return False
    
    def is_uart_connected(self) -> bool:
        """
        @brief 检查UART连接状态
        @return bool 是否已连接
        """
        return self.uart_driver and self.uart_driver.is_connected()
    
    def send_uart_command(self, command: str) -> str:
        """
        @brief 发送UART命令
        @param command 要发送的命令
        @return str 发送结果
        """
        try:
            if not self.uart_driver or not self.uart_driver.is_connected():
                return "错误: UART串口未连接"
            
            result = self.uart_driver.send_command(command)
            logger.info(f"UART命令发送: {command} -> {result}")
            return result
            
        except Exception as e:
            logger.error(f"发送UART命令异常: {e}")
            if self.error_callback:
                self.error_callback(f"发送UART命令异常: {e}")
            return f"错误: {e}"
    
    def receive_uart_data(self) -> str:
        """
        @brief 接收UART数据
        @return str 接收到的数据
        """
        try:
            if not self.uart_driver or not self.uart_driver.is_connected():
                return "错误: UART串口未连接"
            
            data = self.uart_driver.receive_data()
            if data:
                logger.info(f"UART数据接收: {data}")
            return data
            
        except Exception as e:
            logger.error(f"接收UART数据异常: {e}")
            if self.error_callback:
                self.error_callback(f"接收UART数据异常: {e}")
            return f"错误: {e}"
    
    def start_uart_monitor(self) -> bool:
        """
        @brief 启动UART监控
        @return bool 启动是否成功
        """
        try:
            if not self.uart_driver or not self.uart_driver.is_connected():
                logger.warning("UART监控启动失败: UART串口未连接")
                return False
            
            logger.info("UART监控已启动")
            return True
            
        except Exception as e:
            logger.error(f"启动UART监控异常: {e}")
            if self.error_callback:
                self.error_callback(f"启动UART监控异常: {e}")
            return False
    
    def stop_uart_monitor(self) -> bool:
        """
        @brief 停止UART监控
        @return bool 停止是否成功
        """
        try:
            logger.info("UART监控已停止")
            return True
            
        except Exception as e:
            logger.error(f"停止UART监控异常: {e}")
            if self.error_callback:
                self.error_callback(f"停止UART监控异常: {e}")
            return False
